﻿#ifndef METAFUNCTION_H
#define METAFUNCTION_H
#include <string>
#include "metatype.h"
#include "variant.h"
#include <metainfo.h>
class MetaInfo;

class REFLECTX_EXPORT MetaFunction
{
private:
    MetaFunction(IMetaInfoBackend* ,int idx);
public:
    MetaFunction();

    bool isValid() const;

    int Index() const;

	MetaInfo EnclosingMetaInfo() const;

    std::string Signature() const;

    std::vector<MetaTypeId> GetParamTypes() const;

    std::string GetName() const;

    MetaTypeId GetReturnType() const;

    std::vector<std::string> GetFunctionInfos() const;

    template<typename R,typename ...Args>
    void Invoke(void* o,R* r,Args&&... args) const{
        if(MetaType::IdFromType<R>() != GetReturnType()){
            std::cout<<"Return Type Not Compatable!" << std::endl;
            return;
        }

        if(sizeof... (args) != GetParamTypes().size()){
            std::cout<<"Param Types Not Compatable!"<<std::endl;
            return;
        }

        static std::vector<MetaTypeId> types_o = {(MetaType::IdFromType<Args>())...};

        if(types_o != GetParamTypes()){
            std::cout<<"Param Types Not Compatable!"<<std::endl;
            return;
        }

        void* param[std::max(1,(int)sizeof... (args))] = {&args...};
        InvokeImply(o,r,(const void**)param);
    }

    void DynamicInvoke(void* target,Variant & r, const VariantList& param) const;

	void UnSafeInvoke(void* target,void* r,const void** param) const;

private:
    void InvokeImply(void* target,void* r, const void** param) const;
	int LocalIndex() const;
	IMetaInfoBackend* LocalMeta() const;
private:
	std::shared_ptr<IMetaInfoBackend> meta;
    int idx;

	IMetaInfoBackend* localmeta;
	int localIdx;

    friend class MetaInfo;
};

#endif // METAFUNCTION_H
